import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_oldman_health/api/constant.dart';
import 'package:flutter_oldman_health/models/remote_control_model.dart';
import 'package:flutter_oldman_health/models/remote_control_received_model.dart';
import 'package:flutter_oldman_health/utils/event_bus.dart';
import 'package:flutter_oldman_health/widget/listener_container.dart';
import 'package:mqtt_client/mqtt_client.dart';

import 'mqtt_tool.dart';

class RemoteControlTool {
  int listReceivedMessageTime = 0;
  String _mB2ATopic;
  String _mA2BTopic;

  String _userId;
  String _familyId;
  String _sessionId;

  bool active;

  // 收到 OK消息,否则就30秒后关闭
  bool successControl = false;
  bool needPing = true;

  SendTouchScreenModel screenModel = SendTouchScreenModel();
  StreamSubscription<List<MqttReceivedMessage<MqttMessage>>>
      _listenSubscription;

  /// 私有构造函数
  RemoteControlTool._instance();

  static final RemoteControlTool _singleton = RemoteControlTool._instance();

  ///工厂构造函数
  factory RemoteControlTool() => _singleton;
  int sendRequestRemoteControlMsgTime = 0;

  //  建立连接
  Future<bool> connect(String user) async {
    String userName = "java-mqtt";
    String password = "111222";
    if (null != user) {
      _userId = user;
    }
    listReceivedMessageTime = 0;
    _sessionId = _userId + DateTime.now().millisecondsSinceEpoch.toString();
    _mB2ATopic = "p2p/$_sessionId/b2a";
    _mA2BTopic = "p2p/$_sessionId/a2b";
    MqttTool.getInstance()
        .connect(
            Constant.server,
            Constant.FAMILY_REMOTE_CONTROL_CLIENT_ID + _userId,
            userName,
            password,
            port: Constant.port)
        .then((v) {
      if (v.returnCode == MqttConnectReturnCode.connectionAccepted) {
        print("恭喜你~ ====mqtt连接成功");
        _startListen();
        subscribeTopic(_mB2ATopic);
        //对面老人机请求被控制
        subscribeTopic(Constant.FAMILY_REMOTE_CONTROL_TOPIC + _userId);
        subscribeFamilyAddResult();

        if (user == null && _familyId.isNotEmpty) {
          //请求控制老人机
          subscribeTopic("sprocomm/controller/reply$_familyId");
          if (active) {
            sendRequestRemoteControlMsgTime =
                DateTime.now().millisecondsSinceEpoch;
            sendRequestRemoteControlMsg();
            sendRemoteControlMsg(null);
          }
          needPing = true;
          doPing();
        }
        return true;
      } else if (v.returnCode == MqttConnectReturnCode.badUsernameOrPassword) {
        print("mqtt连接失败 --密码错误!!!");
        return false;
      } else {
        print("mqtt连接失败!!!");
        return false;
      }
    });
  }

  //  开启监听消息
  _startListen() {
    print("_startListen 成功 ");
    _listenSubscription = MqttTool.getInstance().updates().listen(_onData);
  }

//  监听消息的具体实现
  _onData(List<MqttReceivedMessage<MqttMessage>> data) {
    final MqttPublishMessage recMess = data[0].payload;
    final String topic = data[0].topic;
    String pt = Utf8Decoder().convert(recMess.payload.message);
    print("MQTT-->监听到消息  topic is  $topic , payload is <-- $pt -->,"
        "${recMess.payload.header.toString()}");

    if ("allow" == pt) {
      //"同意添加好友"
      EventBus().emit("queryFamilyRelation", true);
    } else if ("ok" == pt || "OK" == pt) {
      successControl = true;
      //发起建立远程控制连接 device/hardware
      //sendRemoteControlMsg(null);
    } else if ("cancel" == pt || "Cancel" == pt) {
      EasyLoading.showError("对方不同意控制");
      print('对方不同意控制 myselfCancel');
      EventBus().emit("_disconnect", true);
    } else if ("close" == pt || "Close" == pt) {
      EasyLoading.showInfo("对方关闭连接");
      print('对方关闭连接 myselfCancel');
      EventBus().emit("_disconnect", true);
      // } else if (pt.contains("Ping")) {
      // } else if (pt.contains(Constant.REMOTE_CONTROL_TOUCH_SCREEN_ACK)) {
      //   //TouchScreenAck  触屏交互消息执行结果
    } else if (pt.contains(Constant.REMOTE_CONTROL_CREATE_CONNECTION)) {
      //CreateRemoteControlConnectionAck sendCaptureScreenControl();
      if (RemoteConnectionAckModel.fromJson(json.decode(pt)).request()) {
        sendCaptureScreenControl();
      }
    } else if (pt.contains(Constant.REMOTE_CONTROL_CAPTURE_SCREEN)) {
      listReceivedMessageTime = DateTime.now().millisecondsSinceEpoch;
      //CaptureScreenFinished 收到截图
      EventBus().emit(Constant.REMOTE_CONTROL_CAPTURE_SCREEN, pt);
    } else if (pt.contains(Constant.REMOTE_CONTROL_OLD_CANCEL)) {
      // 老人机主动取消控制请求
      print('老人机主动取消控制请求 myselfCancel');

      EventBus().emit("_disconnect", pt);
    } else if (pt.contains(Constant.REMOTE_CONTROL_CONTROLLER_OK)) {
      // 老人机收到我的同意控制请求
      sendRemoteControlMsg("noNeedAgree");
    } else if (pt.contains(Constant.REMOTE_CONTROL_CONTROLLER)) {
      // 收到老人机控制请求
      EventBus().emit(Constant.REMOTE_CONTROL_CONTROLLER, pt);
    } else if (pt.contains("memberAdd")) {
      EventBus().emit("FamilyAdd", pt);
    } else if (pt.contains(Constant.DEVICE_KICK_OFF)) {
      EventBus().emit(Constant.DEVICE_KICK_OFF, pt);
    }
  }

  void subscribeFamilyAddResult() async {
    subscribeTopic('medical/user/${Constant.enterpriseId}/$_userId');
    subscribeTopic('sprocomm/msg/update/family$_userId');
    subscribeTopic('device/channel/$_userId');
  }

  void replyFamilyAddRequest(String familyId) async {
    String topic1 = "sprocomm/msg/update/family$familyId";
    String topic2 = "sprocomm/msg/update/family$_userId";
    MqttTool.getInstance().publishMessage(topic1, "allow");
    MqttTool.getInstance().publishMessage(topic2, "allow");
  }

  void subscribeFamilyTopic(String family, bool active) async {
    _familyId = family;
    successControl = false;
    this.active = active;
  }

  //发布请求控制老人机消息
  void sendRequestRemoteControlMsg() {
    //OK --> sendRemoteControlMsg()
    String channelId = "_${_familyId}_$_userId";

    String topic1 = "sprocomm/controller/server/send" + _familyId;
    String str1 =
        SendRemoteControlMsgModel(userId: _userId, channelId: channelId)
            .toJson()
            .toString();
    MqttTool.getInstance().publishMessage(topic1, str1);

    //30秒后未接通自动取消
    Future.delayed(Duration(seconds: 30)).then((value) {
      int now = DateTime.now().millisecondsSinceEpoch -
          sendRequestRemoteControlMsgTime;
      print('30秒后如果未接通自动取消 $now myselfCancel $sendRequestRemoteControlMsgTime');

      if (now > 29000) {
        EventBus().emit("delayed_request_control", true);
      }
    });
  }

  //发起建立远程控制连接请求
  void sendRemoteControlMsg(String noNeedAgree) {
    String topic1 = "device/hardware/$_familyId";

    String msg = RemoteControlConnectionModel(
            userId: _userId, noNeedAgree: noNeedAgree, sessionId: _sessionId)
        .toJson()
        .toString();
    print("mqtt hardware !!!  $msg");

    MqttTool.getInstance().publishMessage(topic1, msg);
  }

  //收到"CreateRemoteControlConnectionAck"后控制端向被控端发送截屏消息（一秒一次）
  void sendCaptureScreenControl() {
    int now = DateTime.now().millisecondsSinceEpoch;
    print(
        "mqtt !!!  sendCaptureScreenControl ${now - listReceivedMessageTime}");

    if (now - listReceivedMessageTime > 58000 && listReceivedMessageTime != 0) {
      //超过8秒没收到截屏消息
      print('超过8秒没收到截屏消息 myselfCancel');
      EasyLoading.showInfo("长时间未收到老人端数据，关闭连接");

      EventBus().emit("_disconnect", true);
      return;
    }
    MqttTool.getInstance().publishMessage(_mA2BTopic,
        SendCaptureScreenMsgModel(msgId: now.toString()).toJson().toString());
    Future.delayed(Duration(milliseconds: 800)).then((value) {
      if (needPing) sendCaptureScreenControl();
    });
  }

  //收到截屏完成的消息展示图片
  Uint8List getCaptureScreenFinished(String imageBase64) {
    // Image.memory(bytes,  fit: BoxFit.fill, height: 280, width: 280)
    Uint8List bytes = Base64Decoder().convert(imageBase64);
    return bytes;
  }

  void agreeRemoteControl() {
    MqttTool.getInstance().publishMessage(
        Constant.FAMILY_REMOTE_CONTROL_TOPIC + _userId,
        Constant.REMOTE_CONTROL_CONTROLLER_OK);
  }

  void disAgreeRemoteControl() {
    MqttTool.getInstance().publishMessage(
        Constant.FAMILY_REMOTE_CONTROL_TOPIC + _userId,
        Constant.REMOTE_CONTROL_CONTROLLER_DISAGREE);
  }

  void cancelRemoteControl() {
    MqttTool.getInstance().publishMessage(
        "sprocomm/controller/reply" + _familyId,
        Constant.REMOTE_CONTROL_CONTROLLER_CANCEL);
  }

  doPing() {
    MqttTool.getInstance()
        .publishMessage(_mB2ATopic, PingTimeMsgModel().toJson().toString());

    Future.delayed(Duration(milliseconds: 800)).then((value) {
      // if (needPing) doPing();
    });
  }

  //发送触屏交互消息
  void sendTouchScreenMessage(int eventType, int index, ScreenPoint point) {
    screenModel.msgId = '$eventType${point.x}${point.y}$index';
    screenModel.eventType = eventType;
    screenModel.index = index;
    screenModel.point = point;
    MqttTool.getInstance()
        .publishMessage(_mA2BTopic, screenModel.toJson().toString());
  }

  //  订阅主题
  void subscribeTopic(String topic) {
    MqttTool.getInstance().subscribeMessage(topic);
  }

  //  取消订阅
  void unSubscribeTopic(String topic) {
    MqttTool.getInstance().unsubscribeMessage(topic);
  }

  //  断开连接
  void disFamilyConnect() {
    needPing = false;
    print('disFamilyConnect myselfCancel');
    cancelRemoteControl();
    // unSubscribeTopic("sprocomm/controller/reply" + _familyId);
    // MqttTool.getInstance().publishMessage("sprocomm/controller" + _familyId,
    //     "controller_server_client_my_cancel");
  }

  void disconnect() {
    //发送取消链接信息
    unSubscribeTopic(_mB2ATopic);
    print("mqtt !!!  disconnect");
    MqttTool.getInstance().disconnect();
  }
}
